package edu.towson.cosc.cosc455.brandonmoodyProject1;

import edu.towson.cosc.cosc455.interfaces.SyntaxAnalyzer;

public class MySyntaxAnalyzer implements SyntaxAnalyzer {
	private MyLexicalAnalyzer lexer;
	protected boolean errorFound;
	void setError(){errorFound = true;}
	void resetError(){errorFound = false;}
	boolean getError(){return errorFound;}
	public MySyntaxAnalyzer(MyLexicalAnalyzer lexer) {
        this.lexer = lexer;
    }
	
	public void start() throws CompilerException {
        start(0);
    }
	
	public void start(int Depth) throws CompilerException {
        body(Depth);
        eof(Depth);
    }
	
	/*private void document(int Depth) throws CompilerException {
        body(Depth++);
        lexer.getNextToken();
        
    }*/
    /*private void body(int Depth) throws CompilerException{
        statement(Depth++);
        //list_(Depth);
    }*/
    private void statement(int Depth) throws CompilerException{
        if(lexer.currentToken == Token.TERMINAL_START){
            lexer.getNextToken();
            if(lexer.currentToken==Token.DOCUMENT)
            {
            	 log("<html>",Depth);
            	 document(Depth++);
            }
            else if(lexer.currentToken == Token.HEAD){
            	 log("<head>",Depth);
            head(Depth++);}
            else if(lexer.currentToken == Token.PARAGRAPH){
            	 log("<p>",Depth);
            paragraph(Depth++);}
            else if(lexer.currentToken == Token.TITLE){
            	 log("<title>",Depth);
            title(Depth++);}
            else if(lexer.currentToken == Token.BOLD){
            	 log("<b>",Depth);
            bold(Depth++);}
            else if(lexer.currentToken == Token.ITALICS){
            	 log("<i>",Depth);
            	italics(Depth++);
            }
            else if(lexer.currentToken == Token.AUDIO){
           	 log("<audio>",Depth);
           	audio(Depth++);
           }
            else if(lexer.currentToken == Token.VIDEO){
           	 log("<video>",Depth);
           	video(Depth++);
           }
            else if(lexer.currentToken == Token.USE){
           	 log("<use>",Depth);
           	italics(Depth++);
           }
            else if(lexer.currentToken == Token.DEFINE){
           	 log("<define>",Depth);
           	italics(Depth++);
           }
            else
            {
            	setError();
            }
        }
        else if(lexer.currentToken == Token.TERMINAL_END){
        	lexer.getNextToken();
        	if(lexer.currentToken==Token.DOCUMENT)
            {
            	 log("</html>",Depth);
            	 document(Depth++);
            }
            else if(lexer.currentToken == Token.HEAD){
            	 log("</head>",Depth);
            head(Depth++);}
            else if(lexer.currentToken == Token.PARAGRAPH){
            	 log("</p>",Depth);
            paragraph(Depth++);}
            else if(lexer.currentToken == Token.TITLE){
            	 log("</title>",Depth);
            title(Depth++);}
            else if(lexer.currentToken == Token.BOLD){
            	 log("</b>",Depth);
            bold(Depth++);}
            else if(lexer.currentToken == Token.ITALICS){
            	 log("</i>",Depth);
            	italics(Depth++);
            }
            else if(lexer.currentToken == Token.AUDIO){
           	 log("</audio>",Depth);
           	audio(Depth++);
           }
            else if(lexer.currentToken == Token.VIDEO){
           	 log("</video>",Depth);
           	video(Depth++);
           }
            else if(lexer.currentToken == Token.USE){
           	 log("</use>",Depth);
           	italics(Depth++);
           }
            else if(lexer.currentToken == Token.DEFINE){
           	 log("</define>",Depth);
           	italics(Depth++);
           }
        else
        	setError();
    }
        else if(lexer.currentToken == Token.NEWLINE){
            newLine(Depth++);
        }
        else {
            log(lexer.currentToken.toString(),Depth++);
        }
    }
    //BNF: <STMTLIST'> ::= <STMT> <STMTLIST'> | <EMPTY>
    private void statementList_(int Depth) throws CompilerException{
        if(lexer.currentToken != Token.TERMINAL_START|| lexer.currentToken != Token.TERMINAL_END || lexer.currentToken == Token.NEWLINE ){
            if(lexer.currentToken != Token.DEFINE){
                log("<STMTLIST'>", Depth);
                statement(Depth);
                statementList_(Depth);
            }
        }
        else {
            lexer.getNextToken();
        }

    }
	private void eof(int Depth) throws CompilerException {
        log("<EOF>", Depth);
        if (Token.EOF != lexer.currentToken) {
            String msg = "A End of File (EOF) was expected when '" + lexer.currentToken + "' was found.";
            throw new CompilerException(msg);
        } else {
            lexer.getNextToken();
        }
        }
	private void log(String str, int Depth) {

        for (int i = 0; i < Depth; i++) {
            System.out.print("  ");
        }
        System.out.println(str);
    }
	@Override
	//This method implements the BNF rue for a document <document>::=#START DOCUMENT <variable-define> <head> <body> #END DOCUMENT		
	public void document(int Depth) throws CompilerException {
			if (lexer.currentToken==Token.TERMINAL_START)
			{
		        lexer.getNextToken();
		        if (lexer.currentToken==Token.DOCUMENT)
		        {
		        	log("<html>", Depth);
		        	lexer.getNextToken();
		        	variableDefine(Depth);
		        	head(Depth);
		        	body(Depth);
		        	if(lexer.currentToken==Token.TERMINAL_END)
			        {
			        	lexer.getNextToken();
			        	if(lexer.currentToken==Token.DOCUMENT)
			        	{
			        		log("</html>", Depth);
			        	}
			        }
		        	else
		        	{
		        	String message="an end document annotation was expected where a "+lexer.currentToken+"was found";
		        	throw new CompilerException(message);
		        	}
		        }
		      else
		        {
		        	String message="an start document annotation was expected where a "+lexer.currentToken+"was found";
		        	throw new CompilerException(message);
		        }
		        }
			}
	@Override
	//<body>	::=	 	 <inner-text>	<body>	|	<paragraph>	<body>	|	<bold>	<body>	 |	<italics>	<body>	|	<list>	<body>	|	<EMPTY> 	
	public void body(int Depth) throws CompilerException {
		while(lexer.currentToken==Token.TEXT)
		{
	        log(lexer.currentToken.toString(), Depth);
	        lexer.getNextToken();
		}
	        if (lexer.currentToken==Token.BODY)
	        {
	        	log("<title>", Depth);
	        	lexer.getNextToken();
	        	while (lexer.currentToken==Token.TEXT)
	        		log(lexer.currentToken.toString(),Depth);
	        		lexer.getNextToken();
	        }
	        else
	        {
	        	String message="a start title annotation was expected where a "+lexer.currentToken+"was found";
	        	throw new CompilerException(message);
	        }
	        if(lexer.currentToken==Token.TERMINAL_END)
	        {
	        	lexer.getNextToken();
	        	if(lexer.currentToken==Token.BODY)
	        	{
	        		log("</title>", Depth);
	        		lexer.getNextToken();
	        	}
	        	else
	        	{
	        		String message="an end title annotation was expected where a "+lexer.currentToken+"was found";
	        	throw new CompilerException(message);
	        	}
	        }
		}
	@Override
	//<head>	::=	#START	HEAD	<title>	#END	HEAD	|	<EMPTY> 
	public void head(int Depth) throws CompilerException {
		if (lexer.currentToken==Token.TERMINAL_START)
		{
	        lexer.getNextToken();
	        if (lexer.currentToken==Token.HEAD)
	        {
	        	log("<head>", Depth);
	        	lexer.getNextToken();
	        	title(Depth);
	        	if(lexer.currentToken==Token.TERMINAL_END)
	        	{
	        		lexer.getNextToken();
	        		if(lexer.currentToken==Token.HEAD)
	        		{
	        			log("</head>", Depth);
	        			lexer.getNextToken();
	        		}
	        		else
		        	{
		        		String message="an end head annotation was expected where a "+lexer.currentToken+"was found";
		        	throw new CompilerException(message);
		        	}
	        	}
	        }
	        else
	        {
	        	String message="a start head annotation was expected where a "+lexer.currentToken+"was found";
	        	throw new CompilerException(message);
	        }
		}
	}
@Override
	public void title(int Depth) throws CompilerException {
		if (lexer.currentToken==Token.TERMINAL_START)
		{
	        lexer.getNextToken();
	        if (lexer.currentToken==Token.TITLE)
	        {
	        	log("<title>", Depth);
	        	lexer.getNextToken();
	        	while (lexer.currentToken==Token.TEXT)
	        		log(lexer.currentToken.toString(),Depth);
	        		lexer.getNextToken();
	        }
	        else
	        {
	        	String message="a start title annotation was expected where a "+lexer.currentToken+"was found";
	        	throw new CompilerException(message);
	        }
	        if(lexer.currentToken==Token.TERMINAL_END)
	        {
	        	lexer.getNextToken();
	        	if(lexer.currentToken==Token.TITLE)
	        	{
	        		log("</title>", Depth);
	        		lexer.getNextToken();
	        	}
	        	else
	        	{
	        		String message="an end title annotation was expected where a "+lexer.currentToken+"was found";
	        	throw new CompilerException(message);
	        	}
	        }
		}
	}
	@Override
	//<paragraph>	::=	 #START	PARAGRAPH	<variable-define>	<inner-paragraph>	#END	PARAGRAPH
	public void paragraph(int Depth) throws CompilerException {
		if (lexer.currentToken==Token.TERMINAL_START)
		{
	        lexer.getNextToken();
	        if (lexer.currentToken==Token.PARAGRAPH)
	        {
	        	log("<p>", Depth);
	        	lexer.getNextToken();
	        	variableDefine(Depth);
	        	innerParagraph(Depth);
	        	if(lexer.currentToken==Token.TERMINAL_END)
	        	{
	        		lexer.getNextToken();
	        		if(lexer.currentToken==Token.PARAGRAPH)
	        		{
	        			log("</p>", Depth);
	        			lexer.getNextToken();
	        		}
	        		else
		        	{
		        		String message="an end paragraph annotation was expected where a "+lexer.currentToken+"was found";
		        	throw new CompilerException(message);
		        	}
	        	}
	        }
	        else
	        {
	        	String message="a start paragraph annotation was expected where a "+lexer.currentToken+"was found";
	        	throw new CompilerException(message);
	        }
		}
	}
	@Override
	//<bold>	::=	 	 #START	BOLD	<variable-define>	<inner-text>	#END	BOLD
	public void bold(int Depth) throws CompilerException {
		if (lexer.currentToken==Token.TERMINAL_START)
		{
	        lexer.getNextToken();
	        if (lexer.currentToken==Token.BOLD)
	        {
	        	log("<title>", Depth);
	        	lexer.getNextToken();
	        	while (lexer.currentToken==Token.TEXT)
	        		log(lexer.currentToken.toString(),Depth);
	        		lexer.getNextToken();
	        }
	        else
	        {
	        	String message="a start bold annotation was expected where a "+lexer.currentToken+"was found";
	        	throw new CompilerException(message);
	        }
	        if(lexer.currentToken==Token.TERMINAL_END)
	        {
	        	lexer.getNextToken();
	        	if(lexer.currentToken==Token.BOLD)
	        	{
	        		log("</title>", Depth);
	        		lexer.getNextToken();
	        	}
	        	else
	        	{
	        		String message="an end bold annotation was expected where a "+lexer.currentToken+"was found";
	        	throw new CompilerException(message);
	        	}
	        }
		}
	}
	@Override
	//<italics>	::=	 	 #START	ITALICS	<variable-define>	<inner-text>	#END	ITALICS
	public void italics(int Depth) throws CompilerException {
		if (lexer.currentToken==Token.TERMINAL_START)
		{
	        lexer.getNextToken();
	        if (lexer.currentToken==Token.ITALICS)
	        {
	        	log("<i>", Depth);
	        	lexer.getNextToken();
	        	while (lexer.currentToken==Token.TEXT)
	        		log(lexer.currentToken.toString(),Depth);
	        		lexer.getNextToken();
	        }
	        else
	        {
	        	String message="a start italics annotation was expected where a "+lexer.currentToken+"was found";
	        	throw new CompilerException(message);
	        }
	        if(lexer.currentToken==Token.TERMINAL_END)
	        {
	        	lexer.getNextToken();
	        	if(lexer.currentToken==Token.ITALICS)
	        	{
	        		log("</i>", Depth);
	        		lexer.getNextToken();
	        	}
	        	else
	        	{
	        		String message="an end italics annotation was expected where a "+lexer.currentToken+"was found";
	        	throw new CompilerException(message);
	        	}
	        }
		}
	}
	@Override
	//<list>	::=		 	 #START	LIST	#START	ITEM	<variable-define>	<inner-list>	#END	ITEM	<list-items>	#END	LIST
	public void list(int Depth) throws CompilerException {
		if (lexer.currentToken==Token.TERMINAL_START)
		{
	        lexer.getNextToken();
	        if (lexer.currentToken==Token.LIST)
	        {
	        	log("<ul>", Depth);
	        	lexer.getNextToken();
	        	variableDefine(Depth);
	        	if(lexer.currentToken==Token.TERMINAL_END)
	        	{
	        		lexer.getNextToken();
	        		if(lexer.currentToken==Token.LIST)
	        		{
	        			log("</ul>", Depth);
	        			lexer.getNextToken();
	        		}
	        		else
		        	{
		        		String message="an end list annotation was expected where a "+lexer.currentToken+"was found";
		        	throw new CompilerException(message);
		        	}
	        	}
	        }
	        else
	        {
	        	String message="a start list annotation was expected where a "+lexer.currentToken+"was found";
	        	throw new CompilerException(message);
	        }
		}
	}
	
	//<list-items>	::=		 #START	ITEM	<variable-define>	<inner-list>	#END	ITEM	<list-items>	|	<EMPTY> 
	public void listItems(int Depth) throws CompilerException {
		if (lexer.currentToken==Token.TERMINAL_START)
		{
	        lexer.getNextToken();
	        if (lexer.currentToken==Token.ITEM)
	        {
	        	log("<li>", Depth);
	        	lexer.getNextToken();
	        	variableDefine(Depth);
	        	innerList(Depth);
	        	if(lexer.currentToken==Token.TERMINAL_END)
	        	{
	        		lexer.getNextToken();
	        		if(lexer.currentToken==Token.ITEM)
	        		{
	        			log("</li>", Depth);
	        			lexer.getNextToken();
	        		}
	        		else
		        	{
		        		String message="an end item annotation was expected where a "+lexer.currentToken+"was found";
		        	throw new CompilerException(message);
		        	}
	        	}
	        }
	        else
	        {
	        	String message="a start item annotation was expected where a "+lexer.currentToken+"was found";
	        	throw new CompilerException(message);
	        }
		}
	}
	@Override
	//<audio>	::=	 	 #START	AUDIO	<text>	#END	AUDIO	|	<EMPTY> 
	public void audio(int Depth) throws CompilerException {
			if (lexer.currentToken==Token.TERMINAL_START)
			{
		        lexer.getNextToken();
		        if (lexer.currentToken==Token.AUDIO)
		        {
		        	log("<audio>", Depth);
		        	lexer.getNextToken();
		        	while (lexer.currentToken==Token.TEXT)
		        		log(lexer.currentToken.toString(),Depth);
		        		lexer.getNextToken();
		        }
		        else
		        {
		        	String message="a start audio annotation was expected where a "+lexer.currentToken+"was found";
		        	throw new CompilerException(message);
		        }
		        if(lexer.currentToken==Token.TERMINAL_END)
		        {
		        	lexer.getNextToken();
		        	if(lexer.currentToken==Token.AUDIO)
		        	{
		        		log("</audio>", Depth);
		        		lexer.getNextToken();
		        	}
		        	else
		        	{
		        		String message="an end audio annotation was expected where a "+lexer.currentToken+"was found";
		        		throw new CompilerException(message);
		        	}
		        }
			}
		}
	@Override
	//<video>	::=	 	 #START	VIDEO	<text>	#END	VIDEO	|	<EMPTY> 
	public void video(int Depth) throws CompilerException {
		if (lexer.currentToken==Token.TERMINAL_START)
		{
	        lexer.getNextToken();
	        if (lexer.currentToken==Token.VIDEO)
	        {
	        	log("<video>", Depth);
	        	lexer.getNextToken();
	        	while (lexer.currentToken==Token.TEXT)
	        		log(lexer.currentToken.toString(),Depth);
	        		lexer.getNextToken();
	        }
	        else
	        {
	        	String message="a start video annotation was expected where a "+lexer.currentToken+"was found";
	        	throw new CompilerException(message);
	        }
	        if(lexer.currentToken==Token.TERMINAL_END)
	        {
	        	lexer.getNextToken();
	        	if(lexer.currentToken==Token.VIDEO)
	        	{
	        		log("</video>", Depth);
	        		lexer.getNextToken();
	        	}
	        	else
	        	{
	        		String message="an end video annotation was expected where a "+lexer.currentToken+"was found";
	        	throw new CompilerException(message);
	        	}
	        }
		}
	}
	
	//<variable-define>	::=	 #START	DEFINE	#NAME	<text>	#VALUE	<text>	#END	DEFINE	<variable-define>	|	<EMPTY> 
	public void variableDefine(int Depth) throws CompilerException {
		if (lexer.currentToken==Token.TERMINAL_START)
		{
	        lexer.getNextToken();
	        if (lexer.currentToken==Token.DEFINE)
	        {
	        	log("<define>", Depth);
	        	lexer.getNextToken();
	        	while(lexer.currentToken==Token.TEXT);
	        	{
	        		log(lexer.currentToken.toString(), Depth);
	        		lexer.getNextToken();
	        	}
	        	if(lexer.currentToken==Token.TERMINAL_END)
	        	{
	        		lexer.getNextToken();
	        		if(lexer.currentToken==Token.DEFINE)
	        		{
	        			log("</define>", Depth);
	        			lexer.getNextToken();
	        		}
	        		else
		        	{
		        		String message="an end head annotation was expected where a "+lexer.currentToken+"was found";
		        	throw new CompilerException(message);
		        	}
	        	}
	        }
	        else
	        {
	        	String message="a start head annotation was expected where a "+lexer.currentToken+"was found";
	        	throw new CompilerException(message);
	        }
		}
	}
	
	//<variable-use>	::=	 #START	USE	<text>	#END	USE	|	<EMPTY> 
	public void newLine(int Depth) throws CompilerException {
		if (lexer.currentToken==Token.NEWLINE)
		{
			log("<NEWLINE>", Depth);
	        lexer.getNextToken();
		}
		}
	public void use(int Depth) throws CompilerException {
		if (lexer.currentToken==Token.TERMINAL_START)
		{
	        lexer.getNextToken();
	        if (lexer.currentToken==Token.USE)
	        {
	        	log("<use-variable>", Depth);
	        	lexer.getNextToken();
	        	while (lexer.currentToken==Token.TEXT)
	        		log(lexer.currentToken.toString(),Depth);
	        		lexer.getNextToken();
	        }
	        else
	        {
	        	String message="a start use annotation was expected where a "+lexer.currentToken+"was found";
	        	throw new CompilerException(message);
	        }
	        if(lexer.currentToken==Token.TERMINAL_END)
	        {
	        	lexer.getNextToken();
	        	if(lexer.currentToken==Token.USE)
	        	{
	        		log("</use-variable>", Depth);
	        		lexer.getNextToken();
	        	}
	        	else
	        	{
	        		String message="an end use annotation was expected where a "+lexer.currentToken+"was found";
	        	throw new CompilerException(message);
	        	}
	        }
		}
	}
	public void innerList(int Depth) throws CompilerException {
		bold(Depth);
		italics(Depth);
		list(Depth);
		innerText(Depth);
		
	}
	public void innerParagraph(int Depth) throws CompilerException {
		innerText(Depth);
		bold(Depth);
		italics(Depth);
		list(Depth);
		newLine(Depth);
	}
	public void innerText(int Depth) throws CompilerException {
		use(Depth);
		//text(Depth);
		newLine(Depth);
		audio(Depth);
		video(Depth);
	}
	@Override
	public void document()
			throws edu.towson.cosc.cosc455.brandonmoodyProject1.CompilerException {
		// TODO Auto-generated method stub8
		
	}
	@Override
	public void paragraph()
			throws edu.towson.cosc.cosc455.brandonmoodyProject1.CompilerException {
		// TODO Auto-generated method stub
		
	}
	@Override
	public void bold()
			throws edu.towson.cosc.cosc455.brandonmoodyProject1.CompilerException {
		// TODO Auto-generated method stub
		
	}
	@Override
	public void italics()
			throws edu.towson.cosc.cosc455.brandonmoodyProject1.CompilerException {
		// TODO Auto-generated method stub
		
	}
	@Override
	public void list()
			throws edu.towson.cosc.cosc455.brandonmoodyProject1.CompilerException {
		// TODO Auto-generated method stub
		
	}
	@Override
	public void item()
			throws edu.towson.cosc.cosc455.brandonmoodyProject1.CompilerException {
		// TODO Auto-generated method stub
		
	}
	@Override
	public void audio()
			throws edu.towson.cosc.cosc455.brandonmoodyProject1.CompilerException {
		// TODO Auto-generated method stub
		
	}
	@Override
	public void video()
			throws edu.towson.cosc.cosc455.brandonmoodyProject1.CompilerException {
		// TODO Auto-generated method stub
		
	}
	@Override
	public void define()
			throws edu.towson.cosc.cosc455.brandonmoodyProject1.CompilerException {
		// TODO Auto-generated method stub
		
	}
	@Override
	public void use()
			throws edu.towson.cosc.cosc455.brandonmoodyProject1.CompilerException {
		// TODO Auto-generated method stub
		
	}
	@Override
	public void body() throws CompilerException {
		// TODO Auto-generated method stub
		
	}
	
}